using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Linq.Expressions;
using Rotempco.Core.ORM.Logic;
using Rotempco.Core.Web.Objects.Enums;
using System.Collections.Specialized;
using System.IO;
using Rotempco.Core.Logic;
using Rotempco.Core.ORM.Objects;

namespace Rotempco.Core.Web.Logic
{
    public class UrlLogic
    {
        public static long? GetId<T, TReturn>(Expression<Func<T, TReturn>> expression)
        {
            string parameterValue = GetParameterAsString(expression);
            string parameterName = SymbolExtensions.GetPropertyName(expression);

            if (!string.IsNullOrWhiteSpace(parameterValue))
            {
                long id;
                if (long.TryParse(parameterValue, out id))
                    return id;

                throw new Exception(parameterName + " was not an int64");
            }

            return null;
        }

        public static string GetParameterAsString<T, TReturn>(Expression<Func<T, TReturn>> expression)
        {
            string parameterName = SymbolExtensions.GetPropertyName(expression);

            return GetParameter(parameterName);
        }

        public static string GetParameter(string parameterName)
        {
            HttpRequest request = HttpContext.Current.Request;

            if (!string.IsNullOrWhiteSpace(request[parameterName]))
                return request[parameterName];

            return null;
        }

        public static long? GetParameterAsLong(string parameterName)
        {
            long parameter;
            if (long.TryParse(GetParameter(parameterName), out parameter))
                return parameter;
            return null;
        }

        public static int? GetParameterAsInt(string parameterName)
        {
            int parameter;
            if (int.TryParse(GetParameter(parameterName), out parameter))
                return parameter;
            return null;
        }

        public static double? GetParameterAsDouble(string parameterName)
        {
            double parameter;
            if (double.TryParse(GetParameter(parameterName), out parameter))
                return parameter;
            return null;
        }

        public static bool GetParameterAsBool(string parameterName)
        {
            string publishedString = UrlLogic.GetParameter(parameterName);
            bool published = false;
            bool.TryParse(publishedString, out published);
            return published;
        }

        public static T GetParameterAsEnum<T>(string parameterName, T defaultValue) where T : struct
        {
            T? result = GetParameterAsEnum<T>(parameterName);

            if (result != null)
                return result.Value;

            return defaultValue;
        }

        public static T? GetParameterAsEnum<T>(string parameterName) where T : struct
        {
            string parameterValue = GetParameter(parameterName);

            if (string.IsNullOrWhiteSpace(parameterValue))
                return null;

            T parameterEnumValue;

            if (Enum.TryParse(parameterValue, out parameterEnumValue))
                return parameterEnumValue;

            return null;
        }

        public static Guid? GetParameterAsGuid(string parameterName)
        {
            Guid parameter;
            if (Guid.TryParse(GetParameter(parameterName), out parameter))
                return parameter;
            return null;
        }

        public static DateTime? GetParameterAsDate(string parameterName)
        {
            DateTime parameter;
            if (DateTime.TryParse(GetParameter(parameterName), out parameter))
                return parameter;
            return null;
        }

        public static long? GetIdFromUrl()
        {
            HttpRequest request = HttpContext.Current.Request;
            long returnValue;
            if (!long.TryParse(request["Id"], out returnValue))
                return null;

            return returnValue;
        }

        public static string GetIdFromUrlAsString()
        {
            HttpRequest request = HttpContext.Current.Request;
            string returnValue = request["Id"];
            if (returnValue == null)
                return null;

            return returnValue;
        }

        private static string Goto(string url, List<Pair<string, string>> includeParameters, List<string> excludeParameters)
        {
            HttpRequest request = HttpContext.Current.Request;
            NameValueCollection query = HttpUtility.ParseQueryString(request.Url.Query);

            // Remove parameters
            if (excludeParameters.Count() > 0)
            {
                foreach (string excludeParameter in excludeParameters)
                {
                    if (!string.IsNullOrWhiteSpace(query[excludeParameter]))
                        query.Remove(excludeParameter);
                }
            }

            // Add extra parameters
            if (includeParameters.Count() > 0)
            {
                foreach (Pair<string, string> includeParameter in includeParameters)
                {
                    query[includeParameter.First] = includeParameter.Second;
                }
            }

            // Cleanup:
            List<string> removeParameters = new List<string>();
            foreach (string parameter in query.Keys)
            {
                if (string.IsNullOrWhiteSpace(query[parameter]))
                    removeParameters.Add(parameter);
            }
            foreach (string removeParameter in removeParameters)
                query.Remove(removeParameter);


            return url + "?" + query.ToString();
        }

        public static string Goto(string url, Pair<string, string> includeParameter = null, string excludeParameter = null, List<Pair<string, string>> includeParameters = null, List<string> excludeParameters = null)
        {
            if (includeParameters == null)
                includeParameters = new List<Pair<string, string>>();

            if (excludeParameters == null)
                excludeParameters = new List<string>();

            if (includeParameter != null)
                includeParameters.Add(includeParameter);

            if (excludeParameter != null)
                excludeParameters.Add(excludeParameter);

            return Goto(url, includeParameters, excludeParameters);
        }

        public static string GotoUrl(
                                string url = null,
                                long? id = null,
                                string message = null,
                                string command = null,
                                string returnUrl = null,
                                UrlParameterEnum? extraParameterType = null,
                                string extraParameterValue = null,
                                UrlParameterEnum[] excludeUrlParameterEnums = null)
        {

            HttpRequest request = HttpContext.Current.Request;

            NameValueCollection query = HttpUtility.ParseQueryString(request.Url.Query);

            string gotoUrl = "";
            if (!string.IsNullOrWhiteSpace(query[UrlParameterEnum.ReturnUrl.ToString()]))
                gotoUrl = Decode(query[UrlParameterEnum.ReturnUrl.ToString()]);

            // Remove parameters
            if (excludeUrlParameterEnums != null && excludeUrlParameterEnums.Count() > 0)
            {
                foreach (UrlParameterEnum urlParametersToRemove in excludeUrlParameterEnums)
                {
                    if (!string.IsNullOrWhiteSpace(query[urlParametersToRemove.ToString()]))
                        query.Remove(urlParametersToRemove.ToString());
                }
            }

            // Add extra parameters
            if (extraParameterType != null & extraParameterValue != null && !string.IsNullOrWhiteSpace(extraParameterValue))
                query[extraParameterType.ToString()] = extraParameterValue + "";

            // All Url types:
            if (id.HasValue)
                query["Id"] = id.Value.ToString();
            if (!string.IsNullOrWhiteSpace(message))
                query[UrlParameterEnum.Message.ToString()] = Encode(message);
            if (!string.IsNullOrWhiteSpace(command))
                query[UrlParameterEnum.Command.ToString()] = command;
            if (!string.IsNullOrWhiteSpace(returnUrl))
                query[UrlParameterEnum.ReturnUrl.ToString()] = returnUrl;

            if (string.IsNullOrWhiteSpace(url) && !string.IsNullOrWhiteSpace(gotoUrl))
                url = gotoUrl;

            if (string.IsNullOrWhiteSpace(url))
                url = UrlLogic.GetStaticBaseUrl() + "/Default.aspx";

            string baseUrl = url;
            string parameters = "";
            if (baseUrl.Contains("?"))
            {
                parameters = baseUrl.Substring(baseUrl.LastIndexOf('?') + 1);
                baseUrl = baseUrl.Substring(0, baseUrl.LastIndexOf('?'));
            }

            if (!baseUrl.EndsWith(".aspx") && !baseUrl.EndsWith("/"))
                baseUrl += "/Default.aspx";

            string returnString = baseUrl + "?" + query.ToString();

            if (!string.IsNullOrWhiteSpace(query.ToString()) && !string.IsNullOrWhiteSpace(parameters))
                returnString += "&";

            returnString += parameters;

            return returnString;
        }


        public static string GotoSameUrl(
                                      string url = null,
                                    long? id = null,
                                    string message = null,
                                    string command = null,
                                    string returnUrl = null,
                                    UrlParameterEnum? extraParameterType = null,
                                    string extraParameterValue = null,
                                    UrlParameterEnum[] excludeUrlParameterEnums = null)
        {
            HttpRequest request = HttpContext.Current.Request;

            return GotoUrl(
                            request.Url.AbsolutePath,
                            id: id,
                            message: message,
                            command: command,
                            returnUrl: returnUrl,
                            extraParameterType: extraParameterType,
                            extraParameterValue: extraParameterValue,
                            excludeUrlParameterEnums: excludeUrlParameterEnums);
        }


        public static string Encode(string input)
        {
            if (string.IsNullOrWhiteSpace(input))
                return string.Empty;

            return HttpUtility.UrlEncode(EncodingLogic.Base64Encode(input));
        }

        public static string Decode(string urlString)
        {
            if (string.IsNullOrWhiteSpace(urlString))
                return string.Empty;

            return EncodingLogic.Base64Decode(HttpUtility.UrlDecode(urlString));
        }

        public static bool AspxFileExist(string aspxFileName)
        {
            HttpRequest request = HttpContext.Current.Request;            
            string url = HttpContext.Current.Server.MapPath("/").TrimEnd('\\') + request.Path.Substring(0, request.Path.LastIndexOf('/')).Replace("/", @"\") + @"\" + aspxFileName;
            return File.Exists(url);
        }

        public static string GetStaticBaseUrl()
        {
            HttpRequest request = HttpContext.Current.Request;

            string url = request.Path.Substring(0, request.Path.LastIndexOf('/')).Replace("/WebPages", "");
            return url;
        }

    }
}
